package com.hhf.feiojgatewayservice.filter;

import com.hhf.feiojcommonservice.annotation.AuthCheck;
import com.hhf.feiojcommonservice.common.ErrorCode;
import com.hhf.feiojcommonservice.exception.BusinessException;
import com.hhf.feiojcommonservice.model.enums.RoleEnum;
import com.hhf.feiojcommonservice.model.vo.LoginUserVO;
import com.hhf.feiojcommonservice.utils.JwtUtils;
import com.hhf.feiojgatewayservice.config.AuthProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.annotation.Around;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;

/**
 * @Author hhf
 * @Date 2024/11/4
 * @Description
 */
@Component
@Slf4j
public class GlobalAuthFilter implements GlobalFilter, Ordered {

    private final AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Resource
    private AuthProperties authProperties;


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        String path = exchange.getRequest().getURI().getPath();

        //属于内部服务调用接口,无权限
        if (antPathMatcher.match("/**/inner/**", path)) {
            ServerHttpResponse response = exchange.getResponse();

            response.setStatusCode(HttpStatus.FORBIDDEN);

            DataBuffer buffer = response.bufferFactory().wrap(String.valueOf("禁止访问内部接口").getBytes(StandardCharsets.UTF_8));

            return response.writeWith(Mono.just(buffer));

        }

        //无需校验的接口,直接放行
        if (isExclude(path)) {
            return chain.filter(exchange);
        }

        //1. 获取请求头中的token
        String authorizationHeader = exchange.getRequest().getHeaders().get("authorization").get(0);
        String token = null;
        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            // 去除Bearer标识
            token = authorizationHeader.substring(7); // 去除"Bearer "后的部分
        } else {
            // Authorization头部不符合预期格式
            // 处理逻辑
            ServerHttpResponse response = exchange.getResponse();

            response.setStatusCode(HttpStatus.UNAUTHORIZED);

            DataBuffer buffer = response.bufferFactory().wrap(String.valueOf("Authorization头部不符合预期格式").getBytes(StandardCharsets.UTF_8));

            return response.writeWith(Mono.just(buffer));

        }


        //2. 不存在,拦截
        if (StringUtils.isBlank(token)) {
            ServerHttpResponse response = exchange.getResponse();

            response.setStatusCode(HttpStatus.FORBIDDEN);

            DataBuffer buffer = response.bufferFactory().wrap(String.valueOf("token 不存在,请重新登录").getBytes(StandardCharsets.UTF_8));

            return response.writeWith(Mono.just(buffer));
        }
        //3. 存在,解析token
        Long userId = (Long) JwtUtils.parseToken(token);
        //4. 将token存入请求头中,共下游服务使用
        ServerWebExchange mutateExchange = exchange.mutate()
                .request(r -> r.header("userId", userId.toString()))
                .build();



        //5. 通过权限校验，放行
        return chain.filter(mutateExchange);
    }

    /**
     * 第一个过滤
     *
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }


    private boolean isExclude(String antPath) {

        for (String pathPattern : authProperties.getExcludePaths()) {
            if (antPathMatcher.match(pathPattern, antPath)) {
                return true;
            }
        }
        return false;
    }
}
